library(tidyverse)
library(cowplot)
library(maps)
library(ggforce)
library(viridis)
# library(ggthemes)
studies <- read_csv("../data/studies_gsheet.csv")
sites <- read_csv("../data/sites_gsheet.csv")
df <- studies %>% 
  group_by(site) %>% 
  summarise(Nstudies = n_distinct(studyID),
            Nspecies = n_distinct(species)) %>% 
  mutate(legend_species = ifelse(Nspecies > 4, "more      ", Nspecies))%>%
  left_join(sites)
Joining, by = "site"
df %>% 
  arrange(desc(Nspecies), desc(Nstudies)) %>% 
  mutate(site2 = str_sub(site, 1, 60)) %>% 
  select(site2, Nstudies, Nspecies)
# sanity check that coordinates are in the right country
# within a country, all Xs should be the same color
ggplot(df, aes(x = long, y = lat)) +
  geom_polygon(data = world, aes(group = group), col = "black", fill = "grey90") +
  geom_point(aes(col = country), size = 5, shape = 4, stroke = 2, alpha = .8) +
  coord_fixed(1.3, ylim = c(-55, 83.59961)) +
  scale_color_viridis_d() +
  theme_map() +
  guides(col = "none")

Col & Size = #studies

m <- ggplot(df, aes(x = long, y = lat)) +
  geom_polygon(data = world, aes(group = group), fill = "grey90") +
  geom_point(aes(size = Nstudies, fill = Nstudies), shape = 21, alpha = .8) +
  theme_map() +
  # # to make fill into discrete; overlap with size legend
  # scale_size_area("Number of\nStudies", max_size = 15) +
  # scale_fill_viridis_c("Number of\nStudies", guide = "legend") +
  # to have them side by side
  scale_fill_viridis_c("", breaks = c(1, 20, 40, 60)) +
  scale_size_area("", max_size = 15, breaks = c(1, 20, 40, 60)) +
  theme(legend.box = "horizontal") +
  guides(fill = guide_colorbar(reverse = T, barheight = 10, order = 0), 
         size = guide_legend(keyheight = 2.6, title.theme = element_text(size = 4)))

legend <- get_legend(m)
Removed 3 rows containing missing values (geom_point).
# plot_grid(legend)

mx <- m +
  annotate("rect", ymin = c(24, 31, 24), ymax = c(46, 62, 50), xmin = c(124, -12, -130), 
           xmax = c(146, 32, -64), size = .5, col = "grey", fill = NA) + 
  coord_fixed(1.3, ylim = c(-55, 83.59961)) +
  theme(legend.position = "none")
# japan
m1 <- m + 
  geom_polygon(data = world, aes(group = group), col = "black", fill = "grey90", lwd = .2) +
  geom_point(aes(size = Nstudies, fill = Nstudies), shape = 21, alpha = .8) +
  coord_fixed(1.3, ylim = c(25, 45), xlim = c(125, 145)) +
  theme(legend.position = "none") +
  panel_border(color = "grey", size = .5)

# europe
m2 <- m + 
  geom_polygon(data = world, aes(group = group), col = "black", fill = "grey90", lwd = .2) +
  geom_point(aes(size = Nstudies, fill = Nstudies), shape = 21, alpha = .8) +
  coord_fixed(1.3, ylim = c(32, 60), xlim = c(-10, 30)) +
  theme(legend.position = "none") +
  panel_border(color = "grey", size = .5)

# contiguous us
usa = map("state", plot = FALSE, fill = TRUE) %>% fortify() # "usa"

m3 <- m + 
  geom_polygon(data = world, aes(group = group), col = "black", fill = "grey90", lwd = .2) +
  geom_polygon(data = usa, aes(group = group), col = "black", fill = "grey90", lwd = .2) +
  geom_point(aes(size = Nstudies, fill = Nstudies), shape = 21, alpha = .8) +
  coord_fixed(1.3, ylim = c(25, 49), xlim = c(-127, -67)) +
  theme(legend.position = "none") +
  panel_border(color = "grey", size = .5)
# make bottom row (3 map insets + legend)
bottom_row <- plot_grid(m3, m2, NA, m1, NA, legend, nrow = 1, label_x = -.35, label_y = .95,
                        labels = c(rep("", 5), "Number of Studies"), 
                        rel_widths = c(2, 1.18, .06, .85, .08, .7))
Removed 3 rows containing missing values (geom_point).Removed 3 rows containing missing values (geom_point).Removed 3 rows containing missing values (geom_point).Removed 3 rows containing missing values (geom_point).Cannot convert object of class logical into a grob.Removed 3 rows containing missing values (geom_point).Removed 3 rows containing missing values (geom_point).Cannot convert object of class logical into a grob.
# make whole plot as 1 column, big map on top, bottom row underneath
plot_grid(mx, bottom_row, ncol = 1, rel_heights = c(2.4, 1)) +
  theme(plot.margin = unit(c(.5, .5, 1.5, .5), "cm"))
Removed 3 rows containing missing values (geom_point).

Col = #species, Size = #studies

ms <- ggplot(df, aes(x = long, y = lat)) +
  geom_polygon(data = world, aes(group = group), fill = "grey90") +
  geom_point(aes(size = Nstudies, fill = legend_species), shape = 21, alpha = .8) +
  theme_map() +
  # to have them side by side
  scale_fill_brewer("Species", palette = "Greens") +
  scale_size_area("Studies", max_size = 15, breaks = c(1, 20, 40, 60)) +
  theme(legend.box = "horizontal") +
  guides(fill = guide_legend(override.aes = list(size = 6), keyheight = 1.6, order = 1),
         size = guide_legend(keyheight = 1.6, order = 0))

legend <- get_legend(ms)
Removed 3 rows containing missing values (geom_point).
# plot_grid(legend)

msx <- ms +
  annotate("rect", ymin = c(24, 31, 24), ymax = c(46, 62, 50), xmin = c(124, -12, -130), 
           xmax = c(146, 32, -64), size = .5, col = "grey", fill = NA) + 
  coord_fixed(1.3, ylim = c(-55, 83.59961)) +
  theme(legend.position = "none")
# japan
ms1 <- ms + 
  geom_polygon(data = world, aes(group = group), col = "black", fill = "grey90", lwd = .2) +
  geom_point(aes(size = Nstudies, fill = legend_species), shape = 21, alpha = .8) +
  coord_fixed(1.3, ylim = c(25, 45), xlim = c(125, 145)) +
  theme(legend.position = "none") +
  panel_border(color = "grey", size = .5)

# europe
ms2 <- ms + 
  geom_polygon(data = world, aes(group = group), col = "black", fill = "grey90", lwd = .2) +
  geom_point(aes(size = Nstudies, fill = legend_species), shape = 21, alpha = .8) +
  coord_fixed(1.3, ylim = c(32, 60), xlim = c(-10, 30)) +
  theme(legend.position = "none") +
  panel_border(color = "grey", size = .5)

# contiguous us
usa = map("state", plot = FALSE, fill = TRUE) %>% fortify() # "usa"

ms3 <- ms + 
  geom_polygon(data = world, aes(group = group), col = "black", fill = "grey90", lwd = .2) +
  geom_polygon(data = usa, aes(group = group), col = "black", fill = "grey90", lwd = .2) +
  geom_point(aes(size = Nstudies, fill = legend_species), shape = 21, alpha = .8) +
  coord_fixed(1.3, ylim = c(25, 49), xlim = c(-127, -67)) +
  theme(legend.position = "none") +
  panel_border(color = "grey", size = .5)
# make bottom row (3 map insets + legend)
bottom_row <- plot_grid(ms3, ms2, NA, ms1, NA, legend, nrow = 1, label_x = -.27, label_y = .93,
                        labels = c(rep("", 5), "Number of ..."), 
                        rel_widths = c(2, 1.18, .06, .85, .08, .7))
Removed 3 rows containing missing values (geom_point).Removed 3 rows containing missing values (geom_point).Removed 3 rows containing missing values (geom_point).Removed 3 rows containing missing values (geom_point).Cannot convert object of class logical into a grob.Removed 3 rows containing missing values (geom_point).Removed 3 rows containing missing values (geom_point).Cannot convert object of class logical into a grob.
# make whole plot as 1 column, big map on top, bottom row underneath
plot_grid(msx, bottom_row, ncol = 1, rel_heights = c(2.4, 1)) +
  theme(plot.margin = unit(c(.5, .5, 1.5, .5), "cm"))
Removed 3 rows containing missing values (geom_point).


Session Info

sessionInfo()
R version 3.6.1 (2019-07-05)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Mojave 10.14.5

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] viridis_0.5.1     viridisLite_0.3.0 ggforce_0.3.1     maps_3.3.0        cowplot_1.0.0    
 [6] forcats_0.4.0     stringr_1.4.0     dplyr_0.8.3       purrr_0.3.2       readr_1.3.1      
[11] tidyr_1.0.0       tibble_2.1.3      ggplot2_3.2.1     tidyverse_1.2.1  

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.2         lubridate_1.7.4    lattice_0.20-38    prettyunits_1.0.2  ps_1.3.0          
 [6] assertthat_0.2.1   zeallot_0.1.0      digest_0.6.21      R6_2.4.0           cellranger_1.1.0  
[11] backports_1.1.5    stats4_3.6.1       evaluate_0.14      httr_1.4.1         pillar_1.4.2      
[16] rlang_0.4.0        lazyeval_0.2.2     readxl_1.3.1       rstudioapi_0.10    callr_3.3.2       
[21] rmarkdown_1.16     labeling_0.3       loo_2.1.0          polyclip_1.10-0    munsell_0.5.0     
[26] broom_0.5.2        compiler_3.6.1     modelr_0.1.5       xfun_0.10          rstan_2.19.2      
[31] pkgconfig_2.0.3    base64enc_0.1-3    pkgbuild_1.0.5     htmltools_0.4.0    tidyselect_0.2.5  
[36] gridExtra_2.3      matrixStats_0.55.0 crayon_1.3.4       withr_2.1.2        MASS_7.3-51.4     
[41] grid_3.6.1         nlme_3.1-141       jsonlite_1.6       gtable_0.3.0       lifecycle_0.1.0   
[46] magrittr_1.5       StanHeaders_2.19.0 scales_1.0.0       cli_1.1.0          stringi_1.4.3     
[51] farver_1.1.0       xml2_1.2.2         generics_0.0.2     vctrs_0.2.0        RColorBrewer_1.1-2
[56] tools_3.6.1        glue_1.3.1         tweenr_1.0.1       hms_0.5.1          parallel_3.6.1    
[61] processx_3.4.1     inline_0.3.15      colorspace_1.4-1   rvest_0.3.4        knitr_1.25        
[66] haven_2.1.1       
LS0tCnRpdGxlOiAiU2l0ZXMiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgY3NzOiBzdHlsZS5jc3MKICAgIHRoZW1lOiBwYXBlcgotLS0KCmBgYHtyIHNldHVwLCBtZXNzYWdlPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShjb3dwbG90KQpsaWJyYXJ5KG1hcHMpCmxpYnJhcnkoZ2dmb3JjZSkKbGlicmFyeSh2aXJpZGlzKQojIGxpYnJhcnkoZ2d0aGVtZXMpCmBgYAoKYGBge3IsIG1lc3NhZ2U9RkFMU0V9CnN0dWRpZXMgPC0gcmVhZF9jc3YoIi4uL2RhdGEvc3R1ZGllc19nc2hlZXQuY3N2IikKc2l0ZXMgPC0gcmVhZF9jc3YoIi4uL2RhdGEvc2l0ZXNfZ3NoZWV0LmNzdiIpCmBgYAoKYGBge3J9CmRmIDwtIHN0dWRpZXMgJT4lIAogIGdyb3VwX2J5KHNpdGUpICU+JSAKICBzdW1tYXJpc2UoTnN0dWRpZXMgPSBuX2Rpc3RpbmN0KHN0dWR5SUQpLAogICAgICAgICAgICBOc3BlY2llcyA9IG5fZGlzdGluY3Qoc3BlY2llcykpICU+JSAKICBtdXRhdGUobGVnZW5kX3NwZWNpZXMgPSBpZmVsc2UoTnNwZWNpZXMgPiA0LCAibW9yZSAgICAgICIsIE5zcGVjaWVzKSklPiUKICBsZWZ0X2pvaW4oc2l0ZXMpCmBgYAoKYGBge3J9CmRmICU+JSAKICBhcnJhbmdlKGRlc2MoTnNwZWNpZXMpLCBkZXNjKE5zdHVkaWVzKSkgJT4lIAogIG11dGF0ZShzaXRlMiA9IHN0cl9zdWIoc2l0ZSwgMSwgNjApKSAlPiUgCiAgc2VsZWN0KHNpdGUyLCBOc3R1ZGllcywgTnNwZWNpZXMpCmBgYAoKYGBge3J9CndvcmxkIDwtIG1hcCgid29ybGQiLCBwbG90ID0gRkFMU0UsIGZpbGwgPSBUUlVFKSAlPiUgZm9ydGlmeSgpCmBgYAoKYGBge3IsIGZpZy53aWR0aD0yMCwgZmlnLmhlaWdodD0xMCwgY2FjaGU9VFJVRX0KIyBzYW5pdHkgY2hlY2sgdGhhdCBjb29yZGluYXRlcyBhcmUgaW4gdGhlIHJpZ2h0IGNvdW50cnkKIyB3aXRoaW4gYSBjb3VudHJ5LCBhbGwgWHMgc2hvdWxkIGJlIHRoZSBzYW1lIGNvbG9yCmdncGxvdChkZiwgYWVzKHggPSBsb25nLCB5ID0gbGF0KSkgKwogIGdlb21fcG9seWdvbihkYXRhID0gd29ybGQsIGFlcyhncm91cCA9IGdyb3VwKSwgY29sID0gImJsYWNrIiwgZmlsbCA9ICJncmV5OTAiKSArCiAgZ2VvbV9wb2ludChhZXMoY29sID0gY291bnRyeSksIHNpemUgPSA1LCBzaGFwZSA9IDQsIHN0cm9rZSA9IDIsIGFscGhhID0gLjgpICsKICBjb29yZF9maXhlZCgxLjMsIHlsaW0gPSBjKC01NSwgODMuNTk5NjEpKSArCiAgc2NhbGVfY29sb3JfdmlyaWRpc19kKCkgKwogIHRoZW1lX21hcCgpICsKICBndWlkZXMoY29sID0gIm5vbmUiKQpgYGAKCmBgYHtyfQpnZ3NhdmUoIi4uL2dyYXBocy9tYXAucGRmIiwgd2lkdGggPSAyMCwgaGVpZ2h0ID0gMTAsIHNjYWxlID0gMikKYGBgCgojIENvbCAmIFNpemUgPSAjc3R1ZGllcwoKYGBge3IsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTR9Cm0gPC0gZ2dwbG90KGRmLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQpKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZCwgYWVzKGdyb3VwID0gZ3JvdXApLCBmaWxsID0gImdyZXk5MCIpICsKICBnZW9tX3BvaW50KGFlcyhzaXplID0gTnN0dWRpZXMsIGZpbGwgPSBOc3R1ZGllcyksIHNoYXBlID0gMjEsIGFscGhhID0gLjgpICsKICB0aGVtZV9tYXAoKSArCiAgIyAjIHRvIG1ha2UgZmlsbCBpbnRvIGRpc2NyZXRlOyBvdmVybGFwIHdpdGggc2l6ZSBsZWdlbmQKICAjIHNjYWxlX3NpemVfYXJlYSgiTnVtYmVyIG9mXG5TdHVkaWVzIiwgbWF4X3NpemUgPSAxNSkgKwogICMgc2NhbGVfZmlsbF92aXJpZGlzX2MoIk51bWJlciBvZlxuU3R1ZGllcyIsIGd1aWRlID0gImxlZ2VuZCIpICsKICAjIHRvIGhhdmUgdGhlbSBzaWRlIGJ5IHNpZGUKICBzY2FsZV9maWxsX3ZpcmlkaXNfYygiIiwgYnJlYWtzID0gYygxLCAyMCwgNDAsIDYwKSkgKwogIHNjYWxlX3NpemVfYXJlYSgiIiwgbWF4X3NpemUgPSAxNSwgYnJlYWtzID0gYygxLCAyMCwgNDAsIDYwKSkgKwogIHRoZW1lKGxlZ2VuZC5ib3ggPSAiaG9yaXpvbnRhbCIpICsKICBndWlkZXMoZmlsbCA9IGd1aWRlX2NvbG9yYmFyKHJldmVyc2UgPSBULCBiYXJoZWlnaHQgPSAxMCwgb3JkZXIgPSAwKSwgCiAgICAgICAgIHNpemUgPSBndWlkZV9sZWdlbmQoa2V5aGVpZ2h0ID0gMi42LCB0aXRsZS50aGVtZSA9IGVsZW1lbnRfdGV4dChzaXplID0gNCkpKQoKbGVnZW5kIDwtIGdldF9sZWdlbmQobSkKIyBwbG90X2dyaWQobGVnZW5kKQoKbXggPC0gbSArCiAgYW5ub3RhdGUoInJlY3QiLCB5bWluID0gYygyNCwgMzEsIDI0KSwgeW1heCA9IGMoNDYsIDYyLCA1MCksIHhtaW4gPSBjKDEyNCwgLTEyLCAtMTMwKSwgCiAgICAgICAgICAgeG1heCA9IGMoMTQ2LCAzMiwgLTY0KSwgc2l6ZSA9IC41LCBjb2wgPSAiZ3JleSIsIGZpbGwgPSBOQSkgKyAKICBjb29yZF9maXhlZCgxLjMsIHlsaW0gPSBjKC01NSwgODMuNTk5NjEpKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpgYGAKCmBgYHtyfQojIGphcGFuCm0xIDwtIG0gKyAKICBnZW9tX3BvbHlnb24oZGF0YSA9IHdvcmxkLCBhZXMoZ3JvdXAgPSBncm91cCksIGNvbCA9ICJibGFjayIsIGZpbGwgPSAiZ3JleTkwIiwgbHdkID0gLjIpICsKICBnZW9tX3BvaW50KGFlcyhzaXplID0gTnN0dWRpZXMsIGZpbGwgPSBOc3R1ZGllcyksIHNoYXBlID0gMjEsIGFscGhhID0gLjgpICsKICBjb29yZF9maXhlZCgxLjMsIHlsaW0gPSBjKDI1LCA0NSksIHhsaW0gPSBjKDEyNSwgMTQ1KSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogIHBhbmVsX2JvcmRlcihjb2xvciA9ICJncmV5Iiwgc2l6ZSA9IC41KQoKIyBldXJvcGUKbTIgPC0gbSArIAogIGdlb21fcG9seWdvbihkYXRhID0gd29ybGQsIGFlcyhncm91cCA9IGdyb3VwKSwgY29sID0gImJsYWNrIiwgZmlsbCA9ICJncmV5OTAiLCBsd2QgPSAuMikgKwogIGdlb21fcG9pbnQoYWVzKHNpemUgPSBOc3R1ZGllcywgZmlsbCA9IE5zdHVkaWVzKSwgc2hhcGUgPSAyMSwgYWxwaGEgPSAuOCkgKwogIGNvb3JkX2ZpeGVkKDEuMywgeWxpbSA9IGMoMzIsIDYwKSwgeGxpbSA9IGMoLTEwLCAzMCkpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsKICBwYW5lbF9ib3JkZXIoY29sb3IgPSAiZ3JleSIsIHNpemUgPSAuNSkKCiMgY29udGlndW91cyB1cwp1c2EgPSBtYXAoInN0YXRlIiwgcGxvdCA9IEZBTFNFLCBmaWxsID0gVFJVRSkgJT4lIGZvcnRpZnkoKSAjICJ1c2EiCgptMyA8LSBtICsgCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZCwgYWVzKGdyb3VwID0gZ3JvdXApLCBjb2wgPSAiYmxhY2siLCBmaWxsID0gImdyZXk5MCIsIGx3ZCA9IC4yKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB1c2EsIGFlcyhncm91cCA9IGdyb3VwKSwgY29sID0gImJsYWNrIiwgZmlsbCA9ICJncmV5OTAiLCBsd2QgPSAuMikgKwogIGdlb21fcG9pbnQoYWVzKHNpemUgPSBOc3R1ZGllcywgZmlsbCA9IE5zdHVkaWVzKSwgc2hhcGUgPSAyMSwgYWxwaGEgPSAuOCkgKwogIGNvb3JkX2ZpeGVkKDEuMywgeWxpbSA9IGMoMjUsIDQ5KSwgeGxpbSA9IGMoLTEyNywgLTY3KSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogIHBhbmVsX2JvcmRlcihjb2xvciA9ICJncmV5Iiwgc2l6ZSA9IC41KQpgYGAKCmBgYHtyLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD01LjUsIGNhY2hlPVRSVUV9CiMgbWFrZSBib3R0b20gcm93ICgzIG1hcCBpbnNldHMgKyBsZWdlbmQpCmJvdHRvbV9yb3cgPC0gcGxvdF9ncmlkKG0zLCBtMiwgTkEsIG0xLCBOQSwgbGVnZW5kLCBucm93ID0gMSwgbGFiZWxfeCA9IC0uMzUsIGxhYmVsX3kgPSAuOTUsCiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMocmVwKCIiLCA1KSwgIk51bWJlciBvZiBTdHVkaWVzIiksIAogICAgICAgICAgICAgICAgICAgICAgICByZWxfd2lkdGhzID0gYygyLCAxLjE4LCAuMDYsIC44NSwgLjA4LCAuNykpCgojIG1ha2Ugd2hvbGUgcGxvdCBhcyAxIGNvbHVtbiwgYmlnIG1hcCBvbiB0b3AsIGJvdHRvbSByb3cgdW5kZXJuZWF0aApwbG90X2dyaWQobXgsIGJvdHRvbV9yb3csIG5jb2wgPSAxLCByZWxfaGVpZ2h0cyA9IGMoMi40LCAxKSkgKwogIHRoZW1lKHBsb3QubWFyZ2luID0gdW5pdChjKC41LCAuNSwgMS41LCAuNSksICJjbSIpKQpgYGAKCmBgYHtyfQpnZ3NhdmUoIi4uL2dyYXBocy9tYXBfaW5zZXRzLnBkZiIsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNS41LCBzY2FsZSA9IDIpCmBgYAoKIyBDb2wgPSAjc3BlY2llcywgU2l6ZSA9ICNzdHVkaWVzCgpgYGB7ciwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NH0KbXMgPC0gZ2dwbG90KGRmLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQpKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZCwgYWVzKGdyb3VwID0gZ3JvdXApLCBmaWxsID0gImdyZXk5MCIpICsKICBnZW9tX3BvaW50KGFlcyhzaXplID0gTnN0dWRpZXMsIGZpbGwgPSBsZWdlbmRfc3BlY2llcyksIHNoYXBlID0gMjEsIGFscGhhID0gLjgpICsKICB0aGVtZV9tYXAoKSArCiAgIyB0byBoYXZlIHRoZW0gc2lkZSBieSBzaWRlCiAgc2NhbGVfZmlsbF9icmV3ZXIoIlNwZWNpZXMiLCBwYWxldHRlID0gIkdyZWVucyIpICsKICBzY2FsZV9zaXplX2FyZWEoIlN0dWRpZXMiLCBtYXhfc2l6ZSA9IDE1LCBicmVha3MgPSBjKDEsIDIwLCA0MCwgNjApKSArCiAgdGhlbWUobGVnZW5kLmJveCA9ICJob3Jpem9udGFsIikgKwogIGd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZSA9IDYpLCBrZXloZWlnaHQgPSAxLjYsIG9yZGVyID0gMSksCiAgICAgICAgIHNpemUgPSBndWlkZV9sZWdlbmQoa2V5aGVpZ2h0ID0gMS42LCBvcmRlciA9IDApKQoKbGVnZW5kIDwtIGdldF9sZWdlbmQobXMpCiMgcGxvdF9ncmlkKGxlZ2VuZCkKCm1zeCA8LSBtcyArCiAgYW5ub3RhdGUoInJlY3QiLCB5bWluID0gYygyNCwgMzEsIDI0KSwgeW1heCA9IGMoNDYsIDYyLCA1MCksIHhtaW4gPSBjKDEyNCwgLTEyLCAtMTMwKSwgCiAgICAgICAgICAgeG1heCA9IGMoMTQ2LCAzMiwgLTY0KSwgc2l6ZSA9IC41LCBjb2wgPSAiZ3JleSIsIGZpbGwgPSBOQSkgKyAKICBjb29yZF9maXhlZCgxLjMsIHlsaW0gPSBjKC01NSwgODMuNTk5NjEpKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpgYGAKCmBgYHtyfQojIGphcGFuCm1zMSA8LSBtcyArIAogIGdlb21fcG9seWdvbihkYXRhID0gd29ybGQsIGFlcyhncm91cCA9IGdyb3VwKSwgY29sID0gImJsYWNrIiwgZmlsbCA9ICJncmV5OTAiLCBsd2QgPSAuMikgKwogIGdlb21fcG9pbnQoYWVzKHNpemUgPSBOc3R1ZGllcywgZmlsbCA9IGxlZ2VuZF9zcGVjaWVzKSwgc2hhcGUgPSAyMSwgYWxwaGEgPSAuOCkgKwogIGNvb3JkX2ZpeGVkKDEuMywgeWxpbSA9IGMoMjUsIDQ1KSwgeGxpbSA9IGMoMTI1LCAxNDUpKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgcGFuZWxfYm9yZGVyKGNvbG9yID0gImdyZXkiLCBzaXplID0gLjUpCgojIGV1cm9wZQptczIgPC0gbXMgKyAKICBnZW9tX3BvbHlnb24oZGF0YSA9IHdvcmxkLCBhZXMoZ3JvdXAgPSBncm91cCksIGNvbCA9ICJibGFjayIsIGZpbGwgPSAiZ3JleTkwIiwgbHdkID0gLjIpICsKICBnZW9tX3BvaW50KGFlcyhzaXplID0gTnN0dWRpZXMsIGZpbGwgPSBsZWdlbmRfc3BlY2llcyksIHNoYXBlID0gMjEsIGFscGhhID0gLjgpICsKICBjb29yZF9maXhlZCgxLjMsIHlsaW0gPSBjKDMyLCA2MCksIHhsaW0gPSBjKC0xMCwgMzApKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgcGFuZWxfYm9yZGVyKGNvbG9yID0gImdyZXkiLCBzaXplID0gLjUpCgojIGNvbnRpZ3VvdXMgdXMKdXNhID0gbWFwKCJzdGF0ZSIsIHBsb3QgPSBGQUxTRSwgZmlsbCA9IFRSVUUpICU+JSBmb3J0aWZ5KCkgIyAidXNhIgoKbXMzIDwtIG1zICsgCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZCwgYWVzKGdyb3VwID0gZ3JvdXApLCBjb2wgPSAiYmxhY2siLCBmaWxsID0gImdyZXk5MCIsIGx3ZCA9IC4yKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB1c2EsIGFlcyhncm91cCA9IGdyb3VwKSwgY29sID0gImJsYWNrIiwgZmlsbCA9ICJncmV5OTAiLCBsd2QgPSAuMikgKwogIGdlb21fcG9pbnQoYWVzKHNpemUgPSBOc3R1ZGllcywgZmlsbCA9IGxlZ2VuZF9zcGVjaWVzKSwgc2hhcGUgPSAyMSwgYWxwaGEgPSAuOCkgKwogIGNvb3JkX2ZpeGVkKDEuMywgeWxpbSA9IGMoMjUsIDQ5KSwgeGxpbSA9IGMoLTEyNywgLTY3KSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogIHBhbmVsX2JvcmRlcihjb2xvciA9ICJncmV5Iiwgc2l6ZSA9IC41KQpgYGAKCmBgYHtyLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD01LjUsIGNhY2hlPVRSVUV9CiMgbWFrZSBib3R0b20gcm93ICgzIG1hcCBpbnNldHMgKyBsZWdlbmQpCmJvdHRvbV9yb3cgPC0gcGxvdF9ncmlkKG1zMywgbXMyLCBOQSwgbXMxLCBOQSwgbGVnZW5kLCBucm93ID0gMSwgbGFiZWxfeCA9IC0uMjcsIGxhYmVsX3kgPSAuOTMsCiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMocmVwKCIiLCA1KSwgIk51bWJlciBvZiAuLi4iKSwgCiAgICAgICAgICAgICAgICAgICAgICAgIHJlbF93aWR0aHMgPSBjKDIsIDEuMTgsIC4wNiwgLjg1LCAuMDgsIC43KSkKCiMgbWFrZSB3aG9sZSBwbG90IGFzIDEgY29sdW1uLCBiaWcgbWFwIG9uIHRvcCwgYm90dG9tIHJvdyB1bmRlcm5lYXRoCnBsb3RfZ3JpZChtc3gsIGJvdHRvbV9yb3csIG5jb2wgPSAxLCByZWxfaGVpZ2h0cyA9IGMoMi40LCAxKSkgKwogIHRoZW1lKHBsb3QubWFyZ2luID0gdW5pdChjKC41LCAuNSwgMS41LCAuNSksICJjbSIpKQpgYGAKCmBgYHtyfQpnZ3NhdmUoIi4uL2dyYXBocy9tYXBfaW5zZXRzX2NvbF9zcGVjaWVzLnBkZiIsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNS41LCBzY2FsZSA9IDIpCmBgYAoKCioqKgoKIyBTZXNzaW9uIEluZm8KCmBgYHtyfQpzZXNzaW9uSW5mbygpCmBgYAo=